/** 
 *  @file         basic_fsm_demo.c
 *  @brief        基础状态机实例
 *  @author       Schips
 *  @date         2021-07-21 11:27:52
 *  @version      v1.1
 *  @copyright    Copyright By Schips, All Rights Reserved
 *
 **********************************************************
 */

#include <stdio.h>
#include "openfsm.h"

#define log printf

// 定义数据域
typedef struct {
    int cnt;
} SM_DATA;

/* ------------------- Functions -----------------------------*/
/* 状态机 函数指针 区域 */
void* FSM_FUNCT(init)(void * this_fsm); // 初始化状态
void* FSM_FUNCT(count)(void * this_fsm);//计数状态
void* FSM_FUNCT(done)(void * this_fsm);// 执行完成状态

/* 状态ID ，顺序要求与 procedure_list[] 对应 */
enum procedure_id {
    FSM_STATE(init),
    FSM_STATE(count),
    FSM_STATE(done),
};

/* 状态机跳转列表 */
static Procedure procedure_list[] = {
    FSM_FUNCT(init),
    FSM_FUNCT(count),
    FSM_FUNCT(done),
};

void* FSM_FUNCT(init) (void* this_fsm)
{
    SM_DATA *pd = get_data_entry(this_fsm);

    // 切换到下个状态
    set_next_state(this_fsm, FSM_STATE(count));

    // 数据处理
    pd->cnt = 0;
    log("INIT\n");

    return NULL;
}

void* FSM_FUNCT(count)(void* this_fsm)//计数
{
    SM_DATA *pd = get_data_entry(this_fsm);

    pd->cnt++;

    log("COUNT, %d\n", pd->cnt);
    if ( (pd->cnt) >= 3)
    {
        set_next_state(this_fsm, FSM_STATE(done));
    }

    return NULL;
}

void* FSM_FUNCT(done)(void* this_fsm)//计数完成
{
    // 驻留
    set_next_state(this_fsm, FSM_STATE(done));
    log("DONE\n");
    return NULL;
}

int main(void)
{
    int i = 10;
    // 状态机实例
    FSM fsm_1    = {0};
    // 状态机需要的数据实例
    SM_DATA data = {0};
    state pre_state, cur_state, nxt_state;
    // 用于出错处理
    int err_code;

    // 设置 状态机
    set_procedures(&fsm_1, procedure_list);
    set_data_entry(&fsm_1, &data);
    set_default_state(&fsm_1, FSM_STATE(init));
    set_err_var(&fsm_1, &err_code);

    for (i = 0; i < 10; ++i)
    {
        log("========[%d]========\n", i);

        // 获取状态机执行之前的状态
        pre_state = get_curr_state(&fsm_1);
        log("Before runing: %d\n", pre_state);

        // 执行状态机，使其步进一次
        cur_state = run_state_machine_once(&fsm_1);
        log("Ran :%d\n", cur_state);

        // 获取状态机下次执行的状态
        nxt_state = get_next_state(&fsm_1);
        log("Next :%d\n", nxt_state);

        /* 下列2种情况下的 状态机结束时机 不同 */
#if 1
        // 1、内部执行完成done状态过程，下次才会退出
        // （如果执行过done，，则不再执行）
        if(is_curr_state(&fsm_1, FSM_STATE(done)))
        {
            log("Done after fsm.done\n");
            reset_state_machine(&fsm_1);
            break;
        }
#else
        // 2、在执行done过程之前，就退出
        // 状态机的done状态过程不会被执行
        if(is_next_state(&fsm_1, FSM_STATE(done)))
        {
            log("Done before fsm.done\n");
            reset_state_machine(&fsm_1);
            break;
        }
#endif
    }

    return 0;
}

